home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
afloat.zip
/
FTOA.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-03-14
|
7KB
|
296 lines
PAGE ,132
;----------------------------------------------------------
; FTOA -- version for use with assembly language programs
;
; Copyright Bob Kline 1988
;
; Purpose:
; Convert floating point value to ASCII string
;
; Input:
; DX:AX contain 4-byte real
; DI points to space for new string
; CX specifies precision
;
; Output:
; String stored at address pointed to by DI
;
; Registers changed:
; AX, BX, CX, DX, DI, SI, BP
;
; Other procedures called:
; LDIV10
; FBINTODEC
;
; Comments:
; Calling procedure is responsible for making sure
; that there is enough space for the new string; if
; left side of decimal point would have more than
; 18 digits, the procedure uses scientific notation
; with the precision found in the mantissa rather
; than that specified in the parameter; to force
; the use of scientific notation in all cases, use
; the procedure FTOE instead
;----------------------------------------------------------
PUBLIC FTOA
EXTRN FBINTODEC:NEAR
EXTRN LDIV10:NEAR
.MODEL SMALL
STRING EQU BYTE PTR [DI]
POINTER EQU DI
MAXPREC EQU 8
PRECISION EQU CX
EXPONENT EQU BX
DECPLACES EQU BP
.DATA?
TEMPSTRING DB 11 DUP(?)
.DATA
ROUNDFACTOR LABEL WORD
DD 5,50,500,5000,50000,500000,5000000,50000000
.CODE
FTOA PROC
; at the outset DX:AX = 4-byte real, DI points to start of output
; string, and CX has the specified precision to use
; begin by taking care of zero as a special case
OR AX,AX
JNZ L1
OR DX,DX
JNZ L1
MOV STRING,'0'
INC DI
MOV STRING,0
RET
; bring precision into acceptable range
L1: CMP PRECISION,MAXPREC
JLE L2
MOV PRECISION,MAXPREC
JMP SHORT L3
L2: OR PRECISION,PRECISION
JNS L3
XOR PRECISION,PRECISION
; call fbintodec, which comes back with mantissa in DX:AX,
; sign in low bit of CX, and exponent in BX -- we'll check
; the sign immediately and take care of it so that CX will
; be free to pop the precision back off the stack
L3: PUSH PRECISION
PUSH POINTER
CALL FBINTODEC
POP POINTER
OR CX,CX
JZ L4
MOV STRING,'-'
INC POINTER
L4: POP PRECISION
; use BP to hold number of decimal places required by the
; exponent -- if exponent is negative, decplaces = abs(exponent),
; otherwise decplaces = 0
OR EXPONENT,EXPONENT
JS L5
XOR DECPLACES,DECPLACES
JMP SHORT L6
L5: MOV DECPLACES,EXPONENT
NEG DECPLACES
; if we have more decimal places than called for by the precision,
; we may have to round up the mantissa
L6: CMP DECPLACES,PRECISION
JNA L7
; use SI as index to point into table of amount to add to the
; mantissa to round it up (SI = decplaces - precision - 1)
MOV SI,DECPLACES
SUB SI,PRECISION
DEC SI
; if the number is so small (that is, the absolute value of the
; exponent was so much greater than the precision) that none
; of the digits from the mantissa will be needed, don't bother
; to round the mantissa; don't forget to multiply index (SI)
; by 4 since the size of the table elements is 4 bytes
CMP SI,7
JA L7
SHL SI,1
SHL SI,1
CMP DX,ROUNDFACTOR[SI+2]
JA L8
JB L7
CMP AX,ROUNDFACTOR[SI]
JB L7
; passed all the criteria for rounding -- go ahead and do it
L8: ADD AX,ROUNDFACTOR[SI]
ADC DX,ROUNDFACTOR[SI+2]
; break down mantissa into a temporary string, using SI as the
; index to the string: note that the digits of the string will
; be stored backwards, that is, least significant first, so that
; when we go to move the digits into the output string, we'll
; pick them off from the end and work back to the beginning.
; The algorithm here is:
; while the mantissa is not zero
; divide by 10 and move the remainder into the string
L7: XOR SI,SI
PUSH PRECISION
PUSH EXPONENT
JMP SHORT L9
L10: CALL LDIV10
OR BL,30h
MOV TEMPSTRING[SI],BL
INC SI
L9: OR AX,AX
JNZ L10
OR DX,DX
JNZ L10
POP EXPONENT
POP PRECISION
; get ready for some string moves -- note that we're finished
; with the mantissa itself now, so DX & AX are free for other
; uses
MOV AX,DS
MOV ES,AX
CLD
; if the number is too large (that is, if exponent + digits > 18),
; switch to scientific notation. SI holds the number of digits in
; the temporary string from the mantissa
MOV AX,EXPONENT
ADD AX,SI
CMP AX,18
JNG L11
; save the number of digits in tempstring so we can use SI to point
; to the individual characters in the string, moving backwards
; from the last digit toward the first
PUSH SI
DEC SI
; move one digit, then add a decimal point, followed by the rest
; of the digits
MOV AL,TEMPSTRING[SI]
STOSB
MOV AL,'.'
L13: STOSB
DEC SI
JS L12
MOV AL,TEMPSTRING[SI]
JMP L13
; adjust the exponent: (exponent = exponent + digits - 1) and move
; it into the string
L12: POP SI
ADD EXPONENT,SI
DEC EXPONENT
MOV AL,'e'
STOSB
MOV AL,'+'
STOSB
MOV AX,EXPONENT
MOV CL,10
DIV CL
OR AX,3030h
STOSB
XCHG AH,AL
STOSB
; terminate the string with a null byte and return from the procedure
MOV AL,0
STOSB
RET
; if we made it to here the number was not so big that we had to use
; scientific notation. At this point CX = precision, BX = exponent,
; BP = decimal places, SI = number of digits in tempstring, and DI
; points to next position in the output string -- remember DX and
; AX are no longer needed for the mantissa so we can use them for
; other things
; right now we'll use DX to hold the number of digits from the temporary
; string which should go before the decimal point (digits - decplaces);
; push the number of mantissa digits onto the stack since we'll need
; it later and SI is going to be needed to point to the individual
; digits in tempstring
L11: MOV DX,SI
PUSH SI
DEC SI
SUB DX,DECPLACES
JG L14
; if none of the digits from tempstring go on the left side of the
; decimal point, stick a zero there just for show
MOV AL,'0'
STOSB
JMP SHORT L15
; DX tells us how many of the digits in tempstring should go on the
; left side of the decimal point: put them there
L16: MOV AL,TEMPSTRING[SI]
STOSB
DEC SI
L14: DEC DX
JNS L16
; if we had a positive exponent we need to pad the integer portion
; of the string with zeroes
CMP EXPONENT,0
JNG L15
PUSH CX
MOV CX,EXPONENT
MOV AL,'0'
REP STOSB
POP CX
; if precision is not zero we need to add a decimal point; we'll need
; to use DX to hold the number of digits the mantissa had, since SI
; is still busy pointing to the digits
L15: POP DX
OR PRECISION,PRECISION
JZ L17
MOV AL,'.'
STOSB
; pad decimal places with zeroes on left if necessary: the amount of
; padding needed = decplaces - mantissa digits -- also check to
; make sure we don't overshoot precision specified
SUB DECPLACES,DX
MOV AL,'0'
JMP SHORT L18
L20: STOSB
L18: DEC DECPLACES
JS L19
DEC PRECISION
JNS L20
; now add the remaining digits from the mantissa, if any, and finish off
; with zeroes if precision calls for more digits than we have
JMP SHORT L19
L22: MOV AL,'0'
OR SI,SI
JS L21
MOV AL,TEMPSTRING[SI]
DEC SI
L21: STOSB
L19: DEC PRECISION
JNS L22
; finish off the string with a null byte and come back from procedure
L17: MOV AL,0
STOSB
RET
FTOA ENDP
END